package com.yan.common.aspect;

import com.alibaba.fastjson.JSON;
import com.yan.utils.ResultResponse;
import com.yan.utils.TokenUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;

/**
 * Token 校验
 * 数据签名使用
 */
@Aspect
@Component
public class TokenAspect {

    private final static Logger logger = LoggerFactory.getLogger(TokenAspect.class);


    @Value("${spring.token.ak}")
    private String ak;

    @Value("${spring.token.sk}")
    private String sk;

    public TokenAspect() {

    }

    /**
     * Token
     */
    @Pointcut("@annotation(com.yan.common.annotation.AccessCheck)")
    private void anyMethod() {
    }

    @Around("anyMethod()")
    public Object CheckRequestHead(ProceedingJoinPoint joinPoint) throws Throwable {

        logger.info("check access token start:{}", joinPoint.getArgs());
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        request.setCharacterEncoding("UTF-8");
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        String token = request.getHeader("X-WeshareAuth-Token");
        String[] listAterTokenSplit = token.split("-");
        String wav2 = listAterTokenSplit[0];
        String ak = listAterTokenSplit[1];
        String queryParam = getParamString(request.getParameterMap());
        String requestURI = request.getRequestURI();
        String requestMethod = request.getMethod();
        String sk = this.sk;

        TokenUtils helper = new TokenUtils(ak, sk);

        Object[] args = joinPoint.getArgs();
        String body = JSON.toJSONString(args[0]);
        logger.info("verifyToken requestURI:{} requestMethod:{} }", requestURI, requestMethod);
        boolean flag = helper.verifyToken(token, requestURI, requestMethod, queryParam, body);
        if (flag) {
            Object obj = joinPoint.proceed();
            return obj;
        } else {
            writeResponse(response);
        }
        return null;
    }

    private String getParamString(Map<String, String[]> parameterMap) {
        String queryParam = null;
        if (parameterMap.size() > 0) {
            ArrayList<String> parameterKey = new ArrayList<>(parameterMap.keySet());
            Collections.sort(parameterKey);
            ArrayList<String> keyQuotValues = new ArrayList<>();
            for (String key : parameterKey) {
                keyQuotValues.add(String.format("%s=%s", key, parameterMap.get(key)[0]));
            }
            queryParam = StringUtils.join(keyQuotValues, "&");
        }
        return queryParam;
    }

    private void writeResponse(HttpServletResponse response) throws IOException {
        ResultResponse resultResponse = new ResultResponse();
        resultResponse.setResponseCode("1000");
        resultResponse.setResponseMsg("Fail");
        resultResponse.setObj("almod verify token is invalid");
        String responseMap =
                JSON.toJSONString(resultResponse);
        //        new Gson().toJson(resultResponse);
        response.setContentType("application/json;charset=utf-8");
        response.getOutputStream().write(responseMap.getBytes());
        response.flushBuffer();
    }

}
